﻿using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using BCore.Identity.Users.Caching;
using Core.Caching;
using Core.Domain.Entities;
using Core.Helpers;
using Core.Identity.Common.Interfaces.Common.Interfaces;
using Core.Models;
using MediatR;
using Microsoft.EntityFrameworkCore;

namespace Core.Identity.Users.Features.Commands.Register;

/// <summary>
/// 注册用户
/// </summary>
public class RegisterCommand : ICacheInvalidatorRequest<Result<bool>>
{
    /// <summary>
    /// 用户名
    /// </summary>
    [Required(ErrorMessage = "用户名是必填的")]
    public required string Username { get; set; }

    /// <summary>
    /// 邮箱
    /// </summary>
    [EmailAddress]
    [Required(ErrorMessage = "邮箱是必填的")]
    public required string Email { get; set; }

    /// <summary>
    /// 密码
    /// </summary>
    [Required(ErrorMessage = "密码是必填的")]
    public required string Password { get; set; }

    /// <summary>
    /// 确认密码
    /// </summary>
    [Required(ErrorMessage = "确认密码是必填的")]
    public required string ConfirmPassword { get; set; }

    [JsonIgnore]
    public IEnumerable<string>? Tags => UsersCacheKey.Tags;
}

public class RegisterCommandHandler : IRequestHandler<RegisterCommand, Result<bool>>
{
    private readonly IIdentityDbContext _dbContext;

    public RegisterCommandHandler(IIdentityDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public async Task<Result<bool>> Handle(RegisterCommand request, CancellationToken cancellationToken)
    {
        ExceptionHelper.ThrowIfFalse(request.Password == request.ConfirmPassword, "两次密码不一致");

        var user = await _dbContext.Users.FirstOrDefaultAsync(x => x.Username == request.Username, cancellationToken);
        ExceptionHelper.ThrowIfNotNull(user, "用户已存在");

        user = await _dbContext.Users
           .FirstOrDefaultAsync(x => x.Email == request.Email, cancellationToken);
        ExceptionHelper.ThrowIfNotNull(user, "邮箱已被注册");

        user = User.Register(request.Username, request.Password, request.Email);
        await _dbContext.Users.AddAsync(user, cancellationToken);

        var result = await _dbContext.SaveChangesAsync(cancellationToken) > 0;
        return await Result<bool>.SucceedAsync(result, result, ["注册失败"]);
    }
}
